#include "xcom_node.h"
#include <operator.h>
#include <template.h>
#include <utils/logger.h>
namespace protocol {

void XComNode::SetName(const std::string &name) { name_ = name; }
void XComNode::AddFlow(const std::string &flow) { mapFlow_[flow] = Flow_t(); }
void XComNode::AddFlowExpr(
	const std::string &flow, const std::string &op, const std::string &expr)
{
	if (mapFlow_.find(flow) == mapFlow_.end()) {
		AddFlow(flow);
	}
	Flow_t &flowExpr = mapFlow_[flow];
	Process_t proc;
	proc.call = op;
	proc.expr = WrapExpress(expr);
	flowExpr.procList.push_back(proc);
}
void XComNode::AddFuncPointVar(
	const std::string &func, const std::string &var, const std::string &expr)
{
	if (funcPoints_.find(func) == funcPoints_.end()) {
		funcPoints_[func] = FuncParam_t();
	}
	FuncParam_t &funcpoint = funcPoints_[func];
	if (var == "flow") {
		funcpoint.flow = expr;
	} else if (var == "result") {
		funcpoint.resultExpr = WrapExpress(expr);
	} else if (var == "format") {
		funcpoint.format = expr;
	} else {
		funcpoint.vars[var] = ExprToValue(expr);
	}
}

std::string XComNode::GetFormat(const std::string &funcId)
{
	if (funcPoints_.find(funcId) == funcPoints_.end()) {
		return "%.2f";
	}
	return funcPoints_[funcId].format;
}

void XComNode::SetTemplate(const std::string &temp) { template_ = temp; }
void XComNode::SetId(const std::string &id) { id_ = id; }
const std::string &XComNode::GetId() const
{
	// TODO: insert return statement here
	return id_;
}
const std::string &XComNode::GetTemplate() const
{
	// TODO: insert return statement here
	return template_;
}
const Flow_t XComNode::GetFlow(const std::string &key) const
{
	if (mapFlow_.find(key) == mapFlow_.end()) {
		if (funcPoints_.find(key) != funcPoints_.end()) {
			return GetFlow(GetFuncParam(key).flow);
		}
		return Flow_t();
	}
	return mapFlow_.at(key);
}
bool XComNode::HasFuncId(const std::string &id)
{
	return funcPoints_.find(id) != funcPoints_.end();
};
const FuncParam_t &XComNode::GetFuncParam(const std::string &funcId) const
{
	return funcPoints_.at(funcId);
}

libxcom::OpValue XComNode::ExprToValue(const std::string &strExpr)
{
	std::shared_ptr<libxcom::Express> expr = WrapExpress(strExpr);
	if (expr == nullptr) {
		return libxcom::OpValue::Null();
	}
	libxcom::Operator oprator;

	libxcom::OpValue v = expr->GenCmd(oprator);
	if (v.IsEmpty()) {
		HTELINK_LOG_DEBUG("expr: %s -> %s", strExpr, v.toString());
	}
	return v;
}

std::shared_ptr<libxcom::Express> XComNode::WrapExpress(const std::string &str)
{
	return libxcom::Template::instance()->StaticParse(str);
}
const std::string &XComNode::GetName() const { return name_; }
} // namespace protocol
